/*************************************************************************
    > File Name: 9.Philosophers_dine.c
    > Author: Ykk
    > Mail: 3393579535@qq.com 
    > Created Time: 2023年05月13日 星期六 16时07分59秒
 ************************************************************************/

#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

#define N 5                          /* 哲学家数量 */
#define LEFT (i + N - 1) % N         /* 左边筷子的编号 */
#define RIGHT (i + 1) % N            /* 右边筷子的编号 */

sem_t chopsticks[N];                 /* 信号量数组，每个元素代表一个筷子 */
sem_t room;                          /* 信号量，用于控制哲学家的就餐次序 */

void *philosopher(void *arg) {       /* 哲学家线程的执行函数 */
  int i = *(int *)arg;               
  while (1) {
    printf("Philosopher %d is thinking.\n", i);
    sleep(1);                        /* 思考一会 */

    sem_wait(&room);                 /* 等待空闲的桌子 */
    sem_wait(&chopsticks[LEFT]);     /* 拿起左边的筷子 */
    sem_wait(&chopsticks[RIGHT]);    /* 拿起右边的筷子 */

    printf("Philosopher %d is eating.\n", i);
    sleep(1);                        /* 就餐一会 */

    sem_post(&chopsticks[LEFT]);     /* 放下左边的筷子 */
    sem_post(&chopsticks[RIGHT]);    /* 放下右边的筷子 */
    sem_post(&room);                 /* 离开桌子 */
  }
}

int main() {
  pthread_t tid[N];
  int index[N];
  int i;

  sem_init(&room, 0, N - 1);         /* 初始化信号量 */
  for (i = 0; i < N; i++) {
    sem_init(&chopsticks[i], 0, 1);
    index[i] = i;
    pthread_create(&tid[i], NULL, philosopher, &index[i]);
  }

  for (i = 0; i < N; i++) {
    pthread_join(tid[i], NULL);     /* 等待线程结束 */
  }

  return 0;
}
